package ru.hh.team02.chat.messaging;

import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import ru.hh.team02.chat.client.Client;
import ru.hh.team02.chat.server.Services;

/**
 * class responsible for macro sending logic. current version - one queue with
 * messages per active client
 */
public class SendingService {
    
    /**
     * send personal message
     * @param message - message text
     * @param recipientName
     */
    // XXX [Oleg] There may be no client with this name. Boolean result is required.
    public void SendPersonalMessage(final String message, final String recipientName) {
        if (!Services.dbService.clientExists(recipientName)) {
            return;
        }

        // we start a thread to do a transaction.
        // we need this result only at the time when we will take this message out of the queue.
        FutureTask<Integer> futureId = new FutureTask<Integer>(
                new Callable<Integer>() {
                    public Integer call() {
                        return Services.dbService.putNewPersonalMessageIntoDatabase(message, recipientName);
                    }});
        new Thread(futureId).start();


        if (Services.REGISTRY.hasClientWithName(recipientName)) {
            Client recipient = Services.REGISTRY.getClientByName(recipientName);
            recipient.add(new UnfinishedPersonalMessage(message, futureId));
        }
    }

    /**
     * Send all undelivered messages to the recipient which will be taken from the DB.
     * @param recipientName Recipient name
     */
    public void sendUndeliveredMessages(String recipientName) {
        List<MessageDbEntry> messages = Services.dbService.getAllUndeliveredMessagesToTheClient(recipientName);

        // XXX [Oleg] We should use there analog of addAll (e.g. AddAllToFront) to make it in one blocking
        Client recipient = Services.REGISTRY.getClientByName(recipientName);
        for (MessageDbEntry entry : messages) {
            recipient.add(new PersonalMessage(entry.Message, entry.ID));
        }

    }


    /**
     * Put message to all personal queues of people, who are in the same room as
     * sender
     *
     * @param text
     *            Message text
     * @param senderName
     *            Sender name
     */
    // XXX [Oleg] Why do we need here senderName, and the other methods don't have this parameter.
    // XXX [Oleg] This inconsistency is very noticeable and unpleasant. It is justified?
    public void sendMessageToRoom(String text, String senderName) {
        String room = Services.REGISTRY.getClientRoom(senderName);
        Set<Client> recipients = Services.REGISTRY.getClientsFromRoom(room);

        for (Client recipient : recipients) {
            recipient.add(new PublicMessage(text));
        }

    }
}
